package com.stream;

import com.alibaba.fastjson.JSON;
import com.core.dto.GoodDTO;
import com.core.model.Type1;
import com.core.model.Type2;
import com.core.supplier.GoodSupplier;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.ibm.icu.text.Collator;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * Created with IntelliJ IDEA.
 * User: lxf
 * Date: 2016/11/18
 * Time: 10:29
 * To change this template use Editor | File and Code Templates.
 */
public class StreamApi {

    /**
     * peek  是intermediate操作
     * forEach 是terminal操作
     */
    public static void streamLoop(Stream stream) {
        stream.peek(System.out::println);
    }

    /**
     * 对集合中的元素字符串操作
     */
    public static List<String> streamToUpperCase(Stream<String> stream) {
        return stream.map(String::toUpperCase).collect(Collectors.toList());
    }

    /**
     * 对集合中的元素求平方
     */
    public static List<Integer> streamForSquare(Stream<Integer> stream) {
        return stream.map(i -> i * i).collect(Collectors.toList());
    }

    /**
     * 将流里的所有元素相乘
     */
    public static Integer streamForReduce(Stream<Integer> stream) {
        return stream.reduce(1, (a, b) -> a * b);
    }

    /**
     * Stream.Of() 整合集合中的数据并去重返回
     */
    public static List<Integer> streamForFlatMap(Stream<List<Integer>> stream) {
        return stream.flatMap((childList) -> childList.stream()).distinct().collect(Collectors.toList());
    }

    /**
     * 流转换成字符串
     */
    public static String streamToString(Stream stream) {
        return stream.collect(Collectors.joining()).toString();
    }

    /**
     * 流转换成数组
     */
    public static String[] streamToArray(Stream<String> stream) {
        return stream.toArray(String[]::new);
    }

    /**
     * 找出流中的偶数
     */
    public static int[] streamForEvenNum(IntStream stream) {
        return stream.filter(i -> i % 2 == 0).toArray();
    }


    /**
     * 对流中的字符串按字典顺序排序
     * <p>使用{@link Collator}解决生僻汉字的排序问题
     */
    public static List<String> streamForComparator(Stream<String> stream) {
        return stream.sorted((s1, s2) -> {
            Comparator<Object> com = Collator.getInstance(Locale.CHINA);
            return com.compare(s1, s2);
        }).collect(Collectors.toList());
    }

    /**
     * allmatch 所有匹配返回true
     * anymatch 一个匹配返回true
     * nonematch 无匹配返回true
     */
    public static boolean streamForAllMatch(Stream<GoodDTO> stream) {
        return stream.allMatch(good -> Integer.parseInt(good.getAge()) > 10);
    }

    /**
     * 自定义流,也可用现成的流
     * 以年龄为18分区
     * get(true) 返回符合的
     * get(false) 返回不符合的
     */
    public static Map<Boolean, List<GoodDTO>> streamForPartitioningBy() {
        return Stream.generate(new GoodSupplier()).limit(100).collect(Collectors.partitioningBy(p -> Integer.parseInt(p.getAge()) > 18));
    }

    /**
     * 对流进行分组
     *
     * @param stream
     * @return {1:[{"id":1,"name":"lxf"}],2:[{"id":2,"name":"zxc"}],3:[{"id":3,"name":"qwe"}]}
     */
    public static Map<Integer, List<Type1>> groupingBy(Stream<Type1> stream) {
        return stream.collect(Collectors.groupingBy(Type1::getId));
    }

    /**
     * 生成一个等差数列
     *
     * @return
     */
    public static Integer[] streamForIterate() {
        return Stream.iterate(0, i -> i + 5).limit(10).toArray(Integer[]::new);
    }

    /**
     * list1根据list2里对象的属性进行筛选
     *
     * @return
     */
    public static List<Type2> filterByList() {
        List<Type1> list1 = Arrays.asList(new Type1(1, "lxf"), new Type1(2, "zxc"), new Type1(3, "qwe"));
        List<Type2> list2 = Arrays.asList(new Type2(1, "abc"), new Type2(2, "iop"), new Type2(3, "lxf"));
        //对list2进行筛选，list1对象所有name和list2对象的type不相等的被选中，并返回
        list2 = list2.stream().filter(type2 -> list1.stream().map(Type1::getName).allMatch(name -> !name.equals(type2.getType()))).collect(Collectors.toList());
        for (Type2 t2 : list2) {
            System.out.println(t2.toString());
        }
        return list2;
    }

    public static void main(String[] args) {
        List<Type1> list1 = Arrays.asList(new Type1(1, "lxf"), new Type1(2, "zxc"), new Type1(3, "qwe"));
        System.out.println(JSON.toJSONString(groupingBy(list1.stream())));
    }

}
